package com.jse;

import java.text.ParseException;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

import com.jse.util.Cron;


/**
 * 定时任务服务的友好封装
 * @author QinerG(qinerg@gmail.com)
 */
public abstract class Job {

    private static Log log = Log.get("JOBS");

    private static ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);
    private static ConcurrentHashMap<Object,ScheduledFuture<?>> SETTIMEOUT=new ConcurrentHashMap<>();
    static {
    	Runtime.getRuntime().addShutdownHook(new Thread(Job::close));//注册关闭方法
    }
	
	public static long setInterval(Runnable fn,long delay) {
		Long id=Lang.snowflake();
		SETTIMEOUT.put(id, executor.scheduleAtFixedRate(fn,0,delay,TimeUnit.MILLISECONDS));
		return id;
	}
	public static void clearInterval(Long id) {
		SETTIMEOUT.get(id).cancel(true);
	}
	
	public static long setTimeout(Runnable fn,long delay) {
		Long id=Lang.snowflake();
		SETTIMEOUT.put(id, executor.schedule(fn, delay,TimeUnit.MILLISECONDS));
		return id;
	}
	public static void clearTimeout(Long id) {
		SETTIMEOUT.get(id).cancel(true);
	}
	
	public static void close(){
		executor.close();
	}
	public static Object scheduled(Object id,String cron,Runnable r){
		try {
			Cron c = new Cron(cron);
			SETTIMEOUT.put(id,executor.scheduleAtFixedRate(r,0,
					c.getNextValidTimeAfter(new Date()).getTime()-System.currentTimeMillis(),TimeUnit.MILLISECONDS));
		} catch (ParseException e) {
			throw new RuntimeException("scheduled id:%s cron:%s fail!");
		}
		return null;
	}
	/**
	 * map對象控制任务 启动需要 id,status=1,cron,code 停止最少需要:id,status=0 适合查询出的map对象
	 * @param map jscheduled(Map.of("id",1,"status",1,"cron","quartz表達式","code","(()=>{print(111)})()"));
	 */
	public static void jscheduled(Map<String,Object> map){
		var id=map.get("id");
		var status=map.get("status");
		if(status.toString().equals("1")){
			if(SETTIMEOUT.containsKey(id)){//已存在
				if(SETTIMEOUT.get(id).isCancelled()) {//已取消則刪除重新執行
					SETTIMEOUT.remove(id);
					scheduled(id,map.get("cron").toString(),()->Js.execute(map.get("code").toString()));
				}
			}else {//不存在
				scheduled(id,map.get("cron").toString(),()->Js.execute(map.get("code").toString()));
			}
		}else {
			var s=SETTIMEOUT.remove(id);if(s!=null){s.cancel(true);s=null;}
		}
	}
	
	public static void main(String[] args) throws InterruptedException, ParseException, ExecutionException {
		jscheduled(Map.of("id",1,"status",1,"cron","*/5 * * * * ?","code","(()=>{print(111)})()"));
		Thread.sleep(20000l);
		jscheduled(Map.of("id",1,"status",0,"cron","*/5 * * * * ?","code","(()=>{print(111)})()"));
		System.out.println(SETTIMEOUT.size());
	}
}
